package com.liteng.shadow.core.invoke;

import com.liteng.shadow.core.annotation.Plugin;
import com.liteng.shadow.core.exception.JeeException;
import com.liteng.shadow.core.exception.NotAuthorizeException;
import com.liteng.shadow.core.exception.NotLoginException;
import com.liteng.shadow.core.exception.OpeErrorException;
import com.liteng.shadow.core.utils.SpringContextUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

public class ShadowInvoke
{
  public static Object invoke(String className, String methodName, Object... params)
  {
    try
    {
      Object bean = SpringContextUtil.getBean(className);
      Method method = getMethod(bean, methodName, params);
      return method.invoke(bean, params);
    }
    catch (NotLoginException ne)
    {
      throw new NotLoginException();
    }
    catch (NoSuchBeanDefinitionException e1)
    {
      throw new NotAuthorizeException();
    }
    catch (NoSuchMethodException e2)
    {
      throw new NotAuthorizeException();
    }
    catch (Exception e)
    {
      e.printStackTrace();
      String msg = e.getMessage();
      if ((e instanceof InvocationTargetException)) {
        msg = ((InvocationTargetException)e).getTargetException().getMessage();
      }
      throw new JeeException(msg);
    }
  }
  
  private static Method getMethod(Object bean, String methodName, Object... params)
    throws NoSuchMethodException
  {
    Class clazz = bean.getClass();
    if (clazz.toString().startsWith("class com.sun.proxy"))
    {
      bean = ((SingletonTargetSource)((Advised)bean).getTargetSource()).getTarget();
      clazz = bean.getClass();
    }
    validate(clazz);
    Class<?>[] paramsTypes = new Class[params.length];
    for (int i = 0; i < params.length; i++) {
      paramsTypes[i] = params[i].getClass();
    }
    Method method = clazz.getMethod(methodName, paramsTypes);
    return method;
  }
  
  private static void validate(Class clazz)
  {
    Annotation plugin = clazz.getAnnotation(Plugin.class);
    if (null == plugin) {
      throw new OpeErrorException("��������");
    }
  }
}
